uniform float characterX;
uniform float characterZ;

uniform vec3 headPos;
uniform vec3 neckPos;
uniform vec3 torsoPos;
uniform vec3 rShoulderPos;
uniform vec3 lShoulderPos;
uniform vec3 rElbowPos;
uniform vec3 lElbowPos;
uniform vec3 rHandPos;
uniform vec3 lHandPos;
uniform vec3 rHipPos;
uniform vec3 lHipPos;
uniform vec3 rKneePos;
uniform vec3 lKneePos;
uniform vec3 rFootPos;
uniform vec3 lFootPos;


uniform vec4 torsoOrigin;
uniform vec4 headOrigin;
uniform vec4 neckOrigin;
uniform vec4 rShoulderOrigin;
uniform vec4 lShoulderOrigin;
uniform vec4 rElbowOrigin;
uniform vec4 lElbowOrigin;
uniform vec4 rHandOrigin;
uniform vec4 lHandOrigin;
uniform vec4 rHipOrigin;
uniform vec4 rKneeOrigin;
uniform vec4 lHipOrigin;
uniform vec4 lKneeOrigin;
uniform vec4 rFootOrigin;
uniform vec4 lFootOrigin;



uniform float dt;
varying vec3 eyeNormal;
varying vec3 eyePosition;

uniform sampler2D baseMap;
uniform sampler2D jointTexture;


vec4 multQuat(vec4 q, vec4 r){
	vec3 v = cross(q.xyz, r.xyz) + r.w*q.xyz + q.w*r.xyz;
	float w = q.w*r.w - dot(q.xyz, r.xyz);
	
	return vec4(v.x, v.y, v.z, w);
	
}


vec4 conjugateQuat(vec4 q) {
	return vec4(-q.x, -q.y, -q.z, q.w);
}


vec4 makeQuat(vec3 uq, float theta) {
	return vec4(sin(theta)*uq.x, sin(theta)*uq.y, sin(theta)*uq.z, cos(theta));
}

vec4 quaternionRotate(vec3 a, vec3 b, vec4 vertex, float n) {
	float theta = n*acos(dot(a,b)/(length(a)*length(b)));
	vec3 axb = cross(a, b);
	vec3 uq = normalize(axb);
	vec4 q = makeQuat(uq, theta/2.0);
	
	vec4 rotatedVertex = multQuat(multQuat(q, vertex), conjugateQuat(q));
	
	return rotatedVertex;
}

vec4 rotatePoint(vec4 firstJointOrigin, vec4 secondJointOrigin, vec3 secondJointPos, vec4 vertex, vec4 firstJointWorldOrigin, float n) {
	
	vec3 a = secondJointOrigin.xyz - firstJointOrigin.xyz;
	vec3 b = secondJointPos - firstJointOrigin.xyz;
	
	vec4 point = vertex;
	
	point -= firstJointWorldOrigin;
	point = quaternionRotate(a, b, point, n);
	point += firstJointWorldOrigin;

	return point;
}


void main() {
	vec4 vertex;
	vec3 normal;    

	vertex = gl_Vertex;
	normal = gl_Normal;  

	vec4 neckWorldOrigin = vec4(0.0,1.65,0.0,1.0);
	vec4 rShoulderWorldOrigin = vec4(0.2, 1.45, -0.03, 1.0);
	vec4 lShoulderWorldOrigin = vec4(-0.2, 1.45, -0.03, 1.0);
	vec4 rElbowWorldOrigin = vec4(0.5, 1.42, -0.03, 1.0);
	vec4 lElbowWorldOrigin = vec4(-0.5, 1.42, -0.03, 1.0);
	vec4 rHipWorldOrigin = vec4(0.1, 0.85, -0.03, 1.0);
	vec4 rKneeWorldOrigin = vec4(0.13, 0.45, -0.03, 1.0);
	vec4 lHipWorldOrigin = vec4(-0.1, 0.85, -0.03, 1.0);
	vec4 lKneeWorldOrigin = vec4(-0.13, 0.45, -0.03, 1.0);
	
	vec4 torsoDispl = vec4(torsoPos, 1.0) - torsoOrigin;
	
	headOrigin += torsoDispl;
	neckOrigin += torsoDispl;
	
	rShoulderOrigin += torsoDispl;
	lShoulderOrigin += torsoDispl;
	rElbowOrigin += torsoDispl;
	lElbowOrigin += torsoDispl;
	rHandOrigin += torsoDispl;
	lHandOrigin += torsoDispl;
	rHipOrigin += torsoDispl;
	rKneeOrigin += torsoDispl;
	lHipOrigin += torsoDispl;
	lKneeOrigin += torsoDispl;
	rFootOrigin += torsoDispl;
	lFootOrigin += torsoDispl;
	
	vec3 baseMapColor = texture2D (jointTexture,gl_MultiTexCoord0.st).rgb;
 
	// vertex = vec4(vertex.x + characterX, 0, vertex.z + characterZ, 1.0);
 
	// head rotation
	if(baseMapColor == vec3(0.0,0.0,1.0)) {	
		vertex = rotatePoint(neckOrigin, headOrigin, headPos, vertex, neckWorldOrigin, 1.0);
	} 
	
	// rElbow rotation
	if(baseMapColor == vec3(1.0,1.0,0.0)) {
		vertex = rotatePoint(rShoulderOrigin, rElbowOrigin, rElbowPos, vertex, rShoulderWorldOrigin, 1.0);
	} 
	
	// lElbow rotation
	if(baseMapColor == vec3(0.2,0.2,0.0)) {
		vertex = rotatePoint(lShoulderOrigin, lElbowOrigin, lElbowPos, vertex, lShoulderWorldOrigin, 1.0);
	} 
	
	// rHand rotation
	if(baseMapColor == vec3(1.0,0.0,1.0)) {
		vertex = rotatePoint(rShoulderOrigin, rElbowOrigin, rElbowPos, vertex, rShoulderWorldOrigin, 1.0);
		
		vec4 rElbowWorldOriginRotated = rotatePoint(rShoulderOrigin, rElbowOrigin, rElbowPos, rElbowWorldOrigin, rShoulderWorldOrigin, 1.0);
		
		vertex = rotatePoint(rShoulderOrigin, rElbowOrigin, rElbowPos, vertex, rElbowWorldOriginRotated, -1.0);
		vertex = rotatePoint(rElbowOrigin, rHandOrigin, rHandPos, vertex, rElbowWorldOriginRotated, 1.0);
	}
	
	// lHand rotation
	if(baseMapColor == vec3(0.2,0.0,0.2)) {
		vertex = rotatePoint(lShoulderOrigin, lElbowOrigin, lElbowPos, vertex, lShoulderWorldOrigin, 1.0);
		
		vec4 lElbowWorldOriginRotated = rotatePoint(lShoulderOrigin, lElbowOrigin, lElbowPos, lElbowWorldOrigin, lShoulderWorldOrigin, 1.0);
		
		vertex = rotatePoint(lShoulderOrigin, lElbowOrigin, lElbowPos, vertex, lElbowWorldOriginRotated, -1.0);
		vertex = rotatePoint(lElbowOrigin, lHandOrigin, lHandPos, vertex, lElbowWorldOriginRotated, 1.0);
	}
	
	// rKnee rotation
	if(baseMapColor == vec3(1.0,1.0,1.0)) {	
		vertex = rotatePoint(rHipOrigin, rKneeOrigin, rKneePos, vertex, rHipWorldOrigin, 1.0);
	}
	
	// rFoot rotation
	if(baseMapColor == vec3(0.0,0.2,0.0)) {
		
		vertex = rotatePoint(rHipOrigin, rKneeOrigin, rKneePos, vertex, rHipWorldOrigin, 1.0);
		
		vec4 rKneeWorldOriginRotated = rotatePoint(rHipOrigin, rKneeOrigin, rKneePos, rKneeWorldOrigin, rHipWorldOrigin, 1.0);
		
		vertex = rotatePoint(rHipOrigin, rKneeOrigin, rKneePos, vertex, rKneeWorldOriginRotated, -1.0);
		vertex = rotatePoint(rKneeOrigin, rFootOrigin, rFootPos, vertex, rKneeWorldOriginRotated, 1.0);
		
	}
	
	// lKnee rotation
	if(baseMapColor == vec3(0.2,1.0,0.0)) {
		vertex = rotatePoint(lHipOrigin, lKneeOrigin, lKneePos, vertex, lHipWorldOrigin, 1.0);
	}
	
	// lFoot rotation
	if(baseMapColor == vec3(1.0,0.2,0.2)) {
		vertex = rotatePoint(lHipOrigin, lKneeOrigin, lKneePos, vertex, lHipWorldOrigin, 1.0);
		
		vec4 lKneeWorldOriginRotated = rotatePoint(lHipOrigin, lKneeOrigin, lKneePos, lKneeWorldOrigin, lHipWorldOrigin, 1.0);
		
		vertex = rotatePoint(lHipOrigin, lKneeOrigin, lKneePos, vertex, lKneeWorldOriginRotated, -1.0);
		vertex = rotatePoint(lKneeOrigin, lFootOrigin, lFootPos, vertex, lKneeWorldOriginRotated, 1.0);
	}
	
	
	gl_Position = gl_ModelViewProjectionMatrix * vec4(vertex.x+characterX, vertex.y, vertex.z+characterZ, 1.0);    

    eyeNormal = gl_NormalMatrix * normal;
    
    eyePosition = ( gl_Vertex).xyz; 
    gl_TexCoord[0] = gl_MultiTexCoord0;  
}